#ifndef THREAD_POOL_H
#define THREAD_POOL_H

#include <condition_variable>
#include <functional>
#include <future>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
#include <atomic>
#include <type_traits>

class ThreadPool {
public:
	/// @brief 初始化线程池并启动指定数量的线程
	/// @param numThreads 线程数量，可通过std::thread::hardware_concurrency()获取系统逻辑核心数.
	///  - CPU密集型任务：设为物理核心数(如4核→n=4)，可避免超线程竞争;
	///  - I/O密集型任务：设为2*核心数或更高(如n=8)，平衡计算与I/O等待;
	///  - 混合型任务：   设为核心数+额外I/O线程(如n=6);
	/// @param maxQueueSize 任务队列最大容量，为0表示无限制
	ThreadPool(size_t numThreads, size_t maxQueueSize = 0);

	// 禁止拷贝构造和赋值
	ThreadPool(const ThreadPool &)            = delete;
	ThreadPool &operator=(const ThreadPool &) = delete;

	// 任务入队(支持任意可调用对象及参数)
	// 返回future以便获取结果或异常(兼容C++11的std::result_of)
	template<class F, class... Args>
	auto enqueue(F &&f, Args &&...args) -> std::future<typename std::result_of<F(Args...)>::type>;

	// 查询线程池中线程数量
	size_t size() const;

	// 查询当前正在执行的任务数量(原子操作，无需加锁)
	size_t activeCount() const;

	// 查询等待中的任务数量(需要加锁保护队列)
	size_t pendingCount() const;

	// 阻塞等待所有任务完成(包括队列中的和正在执行的)
	void waitAll();

	// 析构函数：安全关闭线程池(唤醒所有线程并等待退出)
	~ThreadPool();

private:
	// 工作线程的核心逻辑
	void workerThread();

	// 成员变量说明
	std::atomic<bool>                 stop;         // 线程池停止标志(原子操作)
	std::atomic<size_t>               activeTasks;  // 正在执行的任务数(原子操作)
	size_t                            maxQueueSize; // 任务队列最大容量
	std::vector<std::thread>          threads;      // 工作线程集合
	std::queue<std::function<void()>> tasks;        // 待执行任务队列(无参Lambda包装)

	mutable std::mutex      queue_mutex;     // 任务队列的互斥锁
	std::condition_variable queue_not_empty; // 队列非空条件变量(唤醒工作线程)
	std::condition_variable queue_not_full;  // 队列未满条件变量(唤醒入队线程)
	std::condition_variable all_completed;   // 所有任务完成条件变量(唤醒waitAll)
};

// 模板成员函数定义(需放在头文件中)
template<class F, class... Args>
auto ThreadPool::enqueue(F &&f, Args &&...args) -> std::future<typename std::result_of<F(Args...)>::type> {
	// 推导任务返回类型(C++11兼容)
	using ReturnType = typename std::result_of<F(Args...)>::type;

	// 安全封装任务：用std::decay确保F是值类型，避免引用失效
	typedef typename std::decay<F>::type FuncType;
	auto                                 task = std::make_shared<std::packaged_task<ReturnType()>>(std::bind(static_cast<FuncType>(f), std::forward<Args>(args)...));

	// 获取任务的future(用于主线程等待结果)
	std::future<ReturnType> res = task->get_future();

	{
		std::unique_lock<std::mutex> lock(queue_mutex);

		// 线程池已停止，拒绝新任务
		if (stop) {
			throw std::runtime_error("Cannot add tasks to a stopped thread pool");
		}

		// 队列有大小限制时，等待队列有空位
		if (maxQueueSize > 0) {
			queue_not_full.wait(lock, [this] { return tasks.size() < maxQueueSize || stop; });
			// 等待后再次检查停止状态(避免停止后还加任务)
			if (stop) {
				throw std::runtime_error("Cannot add tasks to a stopped thread pool");
			}
		}

		// 将任务包装为无参Lambda，存入队列
		tasks.emplace([task]() { (*task)(); });
	}

	// 通知一个等待线程：有新任务了
	queue_not_empty.notify_one();
	return res;
}

#endif // THREAD_POOL_H
